package com.atguigu.ggkt.order.service.impl;

import com.atguigu.ggkt.box.OrderBox;
import com.atguigu.ggkt.client.activity.CouponInfoFeignClient;
import com.atguigu.ggkt.client.course.CourseFeignClient;
import com.atguigu.ggkt.client.sequence.SequenceFeignClient;
import com.atguigu.ggkt.client.user.UserInfoFeignClient;
import com.atguigu.ggkt.enums.PaymentStatus;
import com.atguigu.ggkt.enums.PaymentType;
import com.atguigu.ggkt.exception.GgktException;
import com.atguigu.ggkt.model.activity.CouponInfo;
import com.atguigu.ggkt.model.order.OrderDetail;
import com.atguigu.ggkt.model.order.OrderInfo;
import com.atguigu.ggkt.model.order.PaymentInfo;
import com.atguigu.ggkt.model.user.UserInfo;
import com.atguigu.ggkt.model.vod.Course;
import com.atguigu.ggkt.order.mapper.OrderDetailMapper;
import com.atguigu.ggkt.order.mapper.OrderInfoMapper;
import com.atguigu.ggkt.order.mapper.PaymentInfoMapper;
import com.atguigu.ggkt.order.service.OrderDetailService;
import com.atguigu.ggkt.order.service.OrderInfoService;
import com.atguigu.ggkt.result.Result;
import com.atguigu.ggkt.utils.AuthContextHolder;
import com.atguigu.ggkt.utils.DateUtil;
import com.atguigu.ggkt.utils.LogTool;
import com.atguigu.ggkt.utils.OrderNoUtils;
import com.atguigu.ggkt.vo.order.OrderFormVo;
import com.atguigu.ggkt.vo.order.OrderInfoQueryVo;
import com.atguigu.ggkt.vo.order.OrderInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单表 订单表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2022-04-28
 */
@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private CourseFeignClient courseFeignClient;

    @Autowired
    private CouponInfoFeignClient couponInfoFeignClient;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    SequenceFeignClient sequenceFeignClient;
    @Resource
    PaymentInfoMapper paymentInfoMapper;
    @Resource
    OrderDetailMapper orderDetailMapper;
    @Resource
    OrderInfoMapper orderInfoMapper;

    //生成订单方法
    @Override
    public String submitOrder(OrderFormVo orderFormVo) {
        //1 获取生成订单条件值
        Long courseId = orderFormVo.getCourseId();
        Long couponId = orderFormVo.getCouponId();
        Long userId = AuthContextHolder.getUserId();

        LogTool.info(this.getClass(), "submitOrder ===> "+courseId+", "+couponId+", "+userId);
        //2 判断当前用户,针对当前课程是否已经生成订单
        //课程id，用户id
//        LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(OrderDetail::getCourseId,courseId);
//        wrapper.eq(OrderDetail::getUserId,userId);
//        OrderDetail orderDetailExists = orderDetailService.getOne(wrapper);
//        if(orderDetailExists != null) {
//            return orderDetailExists.getId();//订单已经存在，直接返回订单id
//        }

        //3 根据课程id查询课程信息
        Course course = courseFeignClient.getById(courseId);
        if(course == null) {
            throw new GgktException(20001,"课程不存在");
        }

        //4 根据用户id查询用户信息
        UserInfo userInfo = userInfoFeignClient.getById(userId);
        if(userInfo == null) {
            throw new GgktException(20001,"用户不存在");
        }

        //5 根据优惠券id查询优惠券信息
        BigDecimal couponReduce = new BigDecimal(0);
        if(couponId != null) {
            CouponInfo couponInfo = couponInfoFeignClient.getById(couponId);
            couponReduce = couponInfo.getAmount();
        }

        //6 封装订单生成需要数据到对象，完成添加订单
        //6.1 封装数据到OrderInfo对象里面，添加订单基本信息表
        Result one = sequenceFeignClient.getOne();
        String id = (String) one.getData();
        System.out.println();
        System.out.println(">>> orderinfo id1: "+id);
        System.out.println();
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(id);
        orderInfo.setUserId(userId);
        orderInfo.setNickName(userInfo.getNickName());
        orderInfo.setPhone(userInfo.getPhone());
        orderInfo.setProvince(userInfo.getProvince());
        orderInfo.setOriginAmount(course.getPrice());
        orderInfo.setCreateTime(DateUtil.now());
        orderInfo.setCouponReduce(couponReduce);
        orderInfo.setFinalAmount(orderInfo.getOriginAmount().subtract(orderInfo.getCouponReduce()));
//        orderInfo.setOutTradeNo(OrderNoUtils.getOrderNo());
        orderInfo.setTradeBody(course.getTitle());
        orderInfo.setOrderStatus("0");
        orderInfoMapper.insert(orderInfo);

        //6.2 封装数据到OrderDetail对象里面，添加订单详情信息表
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setId(orderInfo.getId());
        orderDetail.setUserId(userId);
        orderDetail.setCourseId(courseId);
        orderDetail.setCourseName(course.getTitle());
        orderDetail.setCover(course.getCover());
        orderDetail.setOriginAmount(course.getPrice());
        orderDetail.setCouponReduce(new BigDecimal(0));
        orderDetail.setCreateTime(DateUtil.now());
        orderDetail.setOrderStatus("0");
        orderDetail.setFinalAmount(orderDetail.getOriginAmount().subtract(orderDetail.getCouponReduce()));
        orderDetailMapper.insert(orderDetail);

        //7 更新优惠券状态
        if(null != orderFormVo.getCouponUseId()) {
            couponInfoFeignClient.updateCouponInfoUseStatus(orderFormVo.getCouponUseId(), orderInfo.getId());
        }
        System.out.println(">>> orderinfo id2: "+id);
        //8 返回订单id
        return orderInfo.getId();
    }

    //订单id获取订单信息
    @Override
    public OrderInfoVo getOrderInfoById(String id) {
        //id查询订单基本信息和详情信息
        OrderInfo orderInfo = orderInfoMapper.selectById(id);
        OrderDetail orderDetail = orderDetailService.getById(id);

        //封装OrderInfoVo
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        BeanUtils.copyProperties(orderInfo,orderInfoVo);
        orderInfoVo.setCourseId(orderDetail.getCourseId());
        orderInfoVo.setCourseName(orderDetail.getCourseName());
        return orderInfoVo;
    }

    //更新订单状态 ：已经支付
    @Override
    public void updateOrderStatus(String out_trade_no, OrderBox orderBox) {
        //根据订单号查询订单
        OrderInfo orderInfo = orderBox.getOrderInfo();
        PaymentInfo paymentInfo = orderBox.getPaymentInfo();
        OrderDetail orderDetail = orderBox.getOrderDetail();
        //设置订单状态
        if (!"1".equals(orderInfo.getOrderStatus())) {
            orderInfo.setOrderStatus("1");
            if (null == orderInfo.getPayTime()) {
                orderInfo.setPayTime(DateUtil.now());
            }
            //调用方法更新
            orderInfoMapper.updateById(orderInfo);
        }else {
            LogTool.info(this.getClass(), "already ok. no need to update orderInfo status!");
        }

        if (!"1".equals(orderDetail.getOrderStatus())) {
            orderDetail.setOrderStatus("1");
            //调用方法更新
            orderDetailMapper.updateById(orderDetail);
        }else {
            LogTool.info(this.getClass(), "already ok. no need to update orderDetail status!");
        }

        if (!PaymentStatus.PAID.getCode().toString().equals(paymentInfo.getPaymentStatus())) {
            paymentInfo.setPaymentStatus(PaymentStatus.PAID.getCode().toString());
            paymentInfoMapper.updateById(paymentInfo);
        }else {
            LogTool.info(this.getClass(), "already ok. no need to update paymentInfo status!");
        }
    }

    //订单列表
    @Override
    public Map<String, Object> selectOrderInfoPage(Page<OrderInfo> pageParam,
                                                   OrderInfoQueryVo orderInfoQueryVo) {
        //orderInfoQueryVo获取查询条件
        Long userId = orderInfoQueryVo.getUserId();
        String outTradeNo = orderInfoQueryVo.getOutTradeNo();
        String phone = orderInfoQueryVo.getPhone();
        String createTimeEnd = orderInfoQueryVo.getCreateTimeEnd();
        String createTimeBegin = orderInfoQueryVo.getCreateTimeBegin();
        Integer orderStatus = orderInfoQueryVo.getOrderStatus();

        //判断条件值是否为空，不为空，进行条件封装
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(orderStatus)) {
            wrapper.eq("order_status",orderStatus);
        }
        if(!StringUtils.isEmpty(userId)) {
            wrapper.eq("user_id",userId);
        }
        if(!StringUtils.isEmpty(outTradeNo)) {
            wrapper.eq("out_trade_no",outTradeNo);
        }
        if(!StringUtils.isEmpty(phone)) {
            wrapper.eq("phone",phone);
        }
        if(!StringUtils.isEmpty(createTimeBegin)) {
            wrapper.ge("create_time",createTimeBegin);
        }
        if(!StringUtils.isEmpty(createTimeEnd)) {
            wrapper.le("create_time",createTimeEnd);
        }
        //调用实现条件分页查询
        Page<OrderInfo> pages = orderInfoMapper.selectPage(pageParam, wrapper);
        long totalCount = pages.getTotal();
        long pageCount = pages.getPages();
        List<OrderInfo> records = pages.getRecords();
        //订单里面包含详情内容，封装详情数据，根据订单id查询详情
        records.stream().forEach(item -> {
            this.getOrderDetail(item);
        });

        //所有需要数据封装map集合，最终返回
        Map<String,Object> map = new HashMap<>();
        map.put("total",totalCount);
        map.put("pageCount",pageCount);
        map.put("records",records);
        return map;
    }

    //查询订单详情数据
    private OrderInfo getOrderDetail(OrderInfo orderInfo) {
        //订单id
        String id = orderInfo.getId();
        //查询订单详情
        OrderDetail orderDetail = orderDetailService.getById(id);
        if(orderDetail != null) {
            String courseName = orderDetail.getCourseName();
            orderInfo.getParam().put("courseName",courseName);
            orderInfo.getParam().put("courseId",orderDetail.getCourseId());
        }
        return orderInfo;
    }

    @Override
    public void createPaymentInfo(OrderBox orderBox){
        PaymentInfo paymentInfo = new PaymentInfo();
        PrepayRequest request = orderBox.getPrepayRequest();
        PrepayWithRequestPaymentResponse paymentResponse = orderBox.getPaymentResponse();

        paymentInfo.setAppId(request.getAppid());
        paymentInfo.setId(request.getOutTradeNo());
        paymentInfo.setPaymentStatus(PaymentStatus.UNPAID.getCode().toString());
        paymentInfo.setPaymentType(PaymentType.WEIXIN.getCode().toString());
        paymentInfo.setTotalAmount(new BigDecimal(request.getAmount().getTotal()));
        paymentInfo.setUserId(orderBox.getOrderInfo().getUserId());
        paymentInfo.setCreateTime(DateUtil.now());
        paymentInfo.setIsDeleted(0);
        paymentInfo.setMchid(request.getMchid());
        paymentInfoMapper.insert(paymentInfo);
    }

    //订单列表
    @Override
    public Map<String, Object> selectOrderInfoPageMobile(Page<OrderInfo> pageParam,
                                                         Long userId) {

        //判断条件值是否为空，不为空，进行条件封装
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(userId)) {
            wrapper.eq("user_id",userId);
        }
        //调用实现条件分页查询
        Page<OrderInfo> pages = orderInfoMapper.selectPage(pageParam, wrapper);
        long totalCount = pages.getTotal();
        // 总页码数
        long pageCount = pages.getPages();
        List<OrderInfo> records = pages.getRecords();
        //订单里面包含详情内容，封装详情数据，根据订单id查询详情
        records.stream().forEach(item -> {
            this.getOrderDetail(item);
        });

        //所有需要数据封装map集合，最终返回
        Map<String,Object> map = new HashMap<>();
        map.put("total",totalCount);
        map.put("pageCount",pageCount);
        map.put("records",records);
        return map;
    }

    //课程列表
    @Override
    public Map<String, Object> selectOrderCoursePageMobile(Page<OrderDetail> pageParam,
                                                         Long userId) {

        //判断条件值是否为空，不为空，进行条件封装
        QueryWrapper<OrderDetail> wrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(userId)) {
            wrapper.eq("user_id",userId);
            wrapper.eq("order_status", "1");// 已支付
        }
        //调用实现条件分页查询
        Page<OrderDetail> pages = orderDetailMapper.selectPage(pageParam, wrapper);
        long totalCount = pages.getTotal();
        // 总页码数
        long pageCount = pages.getPages();
        List<OrderDetail> records = pages.getRecords();

        //所有需要数据封装map集合，最终返回
        Map<String,Object> map = new HashMap<>();
        map.put("total",totalCount);
        map.put("pageCount",pageCount);
        map.put("records",records);
        return map;
    }

    //用户是否已买某课程
    @Override
    public boolean isBuy(Long courseId, Long userId){
        QueryWrapper<OrderDetail> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        wrapper.eq("course_id",courseId);
        wrapper.eq("order_status", "1");// 已支付
        boolean bool = SqlHelper.retBool(orderDetailMapper.selectCount(wrapper));

        LogTool.info(this.getClass(), courseId+", userId: "+userId+", isBuy: "+bool);
        return bool;
    }
}
